#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include "Log.hpp"
#include "Thread.hpp"
#include "cond.hpp"
#include "Mutex.hpp"

namespace ThreadPoolMoudle
{
    using namespace ThreadMoudle;
    using namespace LogMoudle;
    using namespace CondMoudle;
    using namespace MutexMoudle;
    static const int gnum = 5;
    template <class T>
    class ThreadPool
    {
    private:
        void WakeUpAllThread()
        {
            // _cond.Broadcast();
             Mutexground lockguard(_mutex);
            if (_sleepnum)
                _cond.Broadcast();
            LOG(loglevel::INFO) << "唤醒所有的休眠线程";
        }
        void WakeUpOne()
        {
            _cond.Signal();
            LOG(loglevel::INFO) << "唤醒一个休眠线程";
        }
        ThreadPool(int num = gnum)
            : _num(num),_isrunning(false),_sleepnum(0)
        {
            for (int i = 0; i < _num; i++)
            {
                _s.emplace_back([this](){ handlertask(); });
            }
        }
        void Start()
        {
            if(_isrunning)
            {
                return;
            }
            _isrunning=true;
            for (auto &thread : _s)
            {
                thread.Start();
                //LOG(loglevel::INFO) << "start new thread success: " << thread.Name();
            }
        }
        ThreadPool(const ThreadPool<T>& as)=delete;
        ThreadPool<T>& operator=(const ThreadPool<T>& as)=delete;
    public:
        static ThreadPool<T>* GetInstance()
        {
            if(_a==nullptr)//外层这个if是防止多执行流争锁，减少争锁的压力
            {
                Mutexground as(_lock);//拿到锁的线程，获取到懒汉模式下的单例对象
                LOG(loglevel::DEBUG)<<"获取单例....";
                if(_a==nullptr)
                {
                    LOG(loglevel::DEBUG) << "首次使用单例, 创建之....";
                    _a = new ThreadPool<T>();
                    _a->Start();
                }
            }
            return _a;
        }
        void Stop()
        {
            if(!_isrunning)
            {
                return;
            }
            _isrunning=false;
            //唤醒所有等待的线程
            WakeUpAllThread();
        }
        void Join()
        {
            for(auto& e:_s)
            {
                e.Join();
            }
        }
        void handlertask()
        {
            char name[128];
            pthread_getname_np(pthread_self(), name, sizeof(name));
            while (true)
            {
                T t;
                {
                    Mutexground lockguard(_mutex);
                    while (_q.empty()&&_isrunning)
                    {
                        _sleepnum++;
                        _cond.wait(_mutex);
                        _sleepnum--;
                    }
                    if(_q.empty()&&!_isrunning)
                    {
                        LOG(loglevel::DEBUG)<<name << " 退出了, 线程池退出&&任务队列为空";
                        break;
                    }
                    //一定有任务
                    t = _q.front(); // 从q中获取任务，任务已经是线程私有的了！！！
                    _q.pop();
                }
                t(); // 处理任务,在非临界区执行
            }
        }
        bool Equeue(const T& in)
        {
            if(_isrunning)
            {
                Mutexground as(_mutex);
                _q.push(in);
                if(_q.size()-_sleepnum==0)
                {
                    WakeUpOne();
                }
                return true;
            }
            return false;
        }
        ~ThreadPool()
        {
        }

    private:
        std::vector<thread> _s;
        int _num;
        std::queue<T> _q;
        Mutex _mutex;
        cond _cond;
        bool _isrunning;
        int _sleepnum;
        static Mutex _lock;
        static ThreadPool<T>* _a;//懒汉模式下的指针对象
    };
     template <typename T>
    ThreadPool<T> *ThreadPool<T>::_a = nullptr;

    template <typename T>
    Mutex ThreadPool<T>::_lock;
}